﻿using CommandSet.bean;
using CommandSet.utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;

namespace CommandSet
{
    internal class Program
    {

        static string cmd_file_path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "cmd.tmp");
        static List<CmdObj> cmds = new List<CmdObj>();

        static void Main(string[] args)
        {

            Console.Title = $"801 命令集合{(CommandLineExecutor.IsUserAdmin() ? "：管理员权限" : "：普通权限")}";

            if (!File.Exists(cmd_file_path))
            {
                RefreshCache();
            }

            if (File.Exists(cmd_file_path))
            {
                DisplayOptions();
            }
            else
            {
                ProgramOutput("未读取到缓存！", 2);
                return;
            }

            Console.ReadKey();
        }

        private static void RefreshCache()
        {
            ProgramOutput("正在刷新网络缓存...", 1);
            try
            {
                NetUtil.downloadTheLatestContent(cmd_file_path);
                ProgramOutput($"命令缓存已刷新：{cmd_file_path}", 1);
            }
            catch (Exception)
            {
                ProgramOutput("网络异常！", 2);
                return;
            }
        }
        private static string ReadCache()
        {
            return File.ReadAllText(cmd_file_path, Encoding.Default);
        }

        private static void DisplayOptions()
        {

            //清理list
            cmds.Clear();
            string cmd_text = ReadCache();
            //解析内容并显示
            string[] decompose1 = cmd_text.Split(new string[] { "(line)" }, StringSplitOptions.RemoveEmptyEntries);

            ProgramOutput($"以下是可用的命令(共{decompose1.Length}条)：", 1);
            foreach (string t1 in decompose1)
            {
                string[] decompose2 = t1.Split(new string[] { "(node)" }, StringSplitOptions.RemoveEmptyEntries);

                CodeTypeEnumeration codeType = StringConversionCodeType(decompose2[1]);
              
                cmds.Add(new CmdObj(decompose2[0].Trim(), decompose2[2].Trim(), decompose2[3].Trim(), codeType));

            }

            foreach (CmdObj item in cmds)
            {
                Console.WriteLine($"{cmds.IndexOf(item) + 1}.[{item.code_type}] {item.name.Trim()}");
            }

            Console.Write("\n请输入对应序号查看命令详情，输入0刷新缓存，输入999重启资源管理器：", 1);

            string num_char = Console.ReadLine();

            int num;
            try
            {
                num = int.Parse(num_char);
            }
            catch (Exception)
            {
                ProgramOutput("输入了错误的序号！", 3);
                Console.Clear();
                DisplayOptions();
                return;
            }

            if (num == 0)
            {
                Console.Clear();
                RefreshCache();
                DisplayOptions();
                return;
            }

            if (num == 999)
            {
                CommandLineExecutor.ExecuteCommand("taskkill /f /im explorer.exe", true);
                Thread.Sleep(1000);
                CommandLineExecutor.ExecuteCommand("start explorer.exe", true);

                Console.Clear();
                DisplayOptions();
                return;
            }

            if (num > cmds.Count || num < 0)
            {
                Console.Clear();
                DisplayOptions();
                return;
            }

            CmdObj cmd = cmds[num - 1];

            Console.Clear();
            Console.WriteLine($"名称：{cmd.name}");
            Console.WriteLine($"描述：{cmd.des}");
            Console.WriteLine($"命令：{cmd.code}");
            Console.WriteLine($"命令类型：{cmd.code_type}");
            

            Console.Write("\n请输入Y进行执行，输入N返回上一级：");
 

            if (Console.ReadLine().Equals("y", StringComparison.OrdinalIgnoreCase))
            {
                Console.WriteLine();
                Exec(cmd);
        
            }
            else
            {
                Console.Clear();
                DisplayOptions();
                return;
            }

        }

        public static void Exec(CmdObj cmdObj)
        {
            string tmpCmdExecFile;

            switch (cmdObj.code_type)
            {
                case CodeTypeEnumeration.CODE_MODE_CMD:
                    
                    tmpCmdExecFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "cmdexec.cmd");
                    File.WriteAllText(tmpCmdExecFile, cmdObj.code);
                    CommandLineExecutor.ExecuteCmdFileWithAdminPrivileges(tmpCmdExecFile);

                    break;
                case CodeTypeEnumeration.CODE_MODE_BAT:

                    tmpCmdExecFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "cmdexec.bat");
                    File.WriteAllText(tmpCmdExecFile, cmdObj.code);
                    CommandLineExecutor.ExecuteCmdFile(tmpCmdExecFile);

                    break;
                case CodeTypeEnumeration.CODE_MODE_BAT_SHELL:

                    tmpCmdExecFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "cmdexec.bat");
                    File.WriteAllText(tmpCmdExecFile, cmdObj.code);
                    CommandLineExecutor.ExecuteCmdFileWithAdminPrivileges(tmpCmdExecFile);

                    break;
                case CodeTypeEnumeration.CODE_MODE_REG:

                    tmpCmdExecFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "cmdexec.reg");
                    Console.WriteLine(tmpCmdExecFile);
                    File.WriteAllText(tmpCmdExecFile, cmdObj.code);
                    CommandLineExecutor.ExecuteCommand($"start {tmpCmdExecFile}",true);
                    ProgramOutput("注册表执行完毕", 0);

                    break;
                default:
                    ProgramOutput("命令非法类型！", 2);
                    break;
            }

            ProgramOutput("按任意键返回上一级", 1);
            Console.ReadKey();
            Console.Clear();
            DisplayOptions();

        }

        /// <summary>
        /// 代码类型字符串转换代码类型
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private static CodeTypeEnumeration StringConversionCodeType(string str)
        {
            CodeTypeEnumeration codeType;

            switch (str.Trim())
            {
                case "cmd":
                    return CodeTypeEnumeration.CODE_MODE_CMD;
                case "bat":
                    return CodeTypeEnumeration.CODE_MODE_BAT;
                case "reg":
                    return CodeTypeEnumeration.CODE_MODE_REG;
                case "bat2":
                    return CodeTypeEnumeration.CODE_MODE_BAT_SHELL;
                default:
                    codeType = CodeTypeEnumeration.CODE_MODE_CMD;
                    return codeType;
            }
        }


        /// <summary>
        /// 程序输出，带前缀
        /// </summary>
        /// <param name="text"></param>
        /// <param name="out_mode"></param>
        private static void ProgramOutput(object text, int out_mode)
        {
            string prefix;
            switch (out_mode)
            {
                case 0:
                    prefix = "[程序输出]";
                    break;
                case 1:
                    prefix = "[程序输出]";
                    break;
                case 2:
                    prefix = "[程序异常]";
                    break;
                case 3:
                    prefix = "[程序警告]";
                    break;
                default:
                    prefix = "[异常标识符]";
                    break;
            }

            Console.WriteLine($"{prefix}\n{text}\n");
        }

    }
}
